COMP3141 Software System Design and Implementation

COMP3141: Software System Design and Implementation

Term 2, 2023

Code and Notes (Week 3 Thursday)

Table of Contents

1 Live code

This is all the code I wrote during the practical, plus some notes on stuff I didn't have time to get to. No guarantee that it makes any sense out of context.

module PracticeWeekTwo where

import Test.QuickCheck
import Data.List.NonEmpty (group, NonEmpty, head)
import Data.Char
import Data.List (sort, sortOn)

-- these are the notes from today's practical class.
-- we skipped the induction section, as we covered it last week.
-- nevertheless, i will copy those notes here. If you want to 
-- see them being written, look for the recorded practical from 
-- week two.
{- INDUCTION QN
  goal: 
  map f (map g xs) = map (f . g) xs

  definition of map:
  map :: (a -> b) -> [a] -> [b]
  map _ []     = []                 -- eq 1
  map f (x:xs) = f x:map f xs       -- eq 2

  proof:

  proof by structural induction on the list xs.

  case for the empty list:
  map f (map g []) = map f ([]) -- eq 1
                   = map f []
                   = []
  map (f . g) [] = [] -- eq1
     base case proven!

  inductive case:
  map f (map g xs) = map (f . g) xs -- IH

  map f (map g (x:xs)) = map f (g x : map g xs) -- eq 2
                       = f (g x) : map f (map g xs) -- eq 2
                       = f (g x) : map (f . g) xs -- IH
                       = (f . g) x : map (f . g) xs
                       = map (f . g) (x:xs)
-}

-- the below was actually written during the practical in week 3.

data Natural = Zero
             | Succ Natural

-- q 1
toInt :: Natural -> Int
toInt Zero = 0
toInt (Succ n) = 1 + toInt n

-- q 2
instance Show Natural where
    show n = show $ toInt n

instance Eq Natural where
    Zero == Zero = True
    Succ n == Succ m = n == m
    Succ _ == Zero = False
    Zero == Succ _ = False

toNatural :: Int -> Natural
toNatural n | n<=0 = Zero
            | otherwise = Succ (toNatural (n-1))

instance Arbitrary Natural where
  arbitrary = (toNatural . getNonNegative) <$> arbitrary

natEqReflProp :: Natural -> Bool
natEqReflProp n = n == n

natEqTransProp :: Natural -> Natural -> Natural -> Property
natEqTransProp a b c = a == b ==> b == c ==> a == c


-- q3
{-
  we want to know that Eq is an equivalence relation.

  reflexivity means a == a
  transitivity means a == b /\ b == c ==> a == c 
  symmetry means a == b ==> b == a 

-}

-- q4

natPlus :: Natural -> Natural -> Natural
natPlus Zero m = m
natPlus (Succ n) m = Succ (natPlus n m)

natPlusSymmProp :: Natural -> Natural -> Bool
natPlusSymmProp a b = natPlus a b == natPlus b a

{-
  what will 2+0 look like?
  Succ (Succ Zero) + Zero
     = Succ (Succ Zero + Zero)
     = Succ (Succ (Zero + Zero))
     = Succ (Succ Zero)
-}

natMult :: Natural -> Natural -> Natural
natMult Zero m = Zero
natMult (Succ n) m = natPlus m (natMult n m)

natSub :: Natural -> Natural -> Natural
natSub n Zero = n
natSub Zero _ = Zero
natSub (Succ n) (Succ m) = natSub n m

-- q5
instance Ord Natural where
    compare Zero Zero = EQ
    compare Zero (Succ _) = LT
    compare (Succ _) Zero = GT
    compare (Succ n) (Succ m) = compare n m

{-
-- another approach using other stuff (this isn't the best solution)
instance Ord Natural where
    compare n m | n == m = EQ
                | natSub n m == Zero = LT
                | otherwise = GT
-}

-- monoids

-- a semigroup is
-- a type and a binary operation <>
-- that operation must be associative

-- a monoid is
-- a type and a bunary operation <>
-- AND an identity element
-- the operation is associative
-- we also have x <> id = x
--          and id <> x = x

{- q1 and q3
  LISTS can be a monoid
  ++ and []

  other ideas?
  zipplus:
  [1, 2, 3, 4, 5]
  [5, 4, 5]
  <>
  [6, 6, 8, 4, 5]
  id element: []

  zipplus':
  [1, 2, 3, 4, 5]
  [5, 4, 5]
  <>
  [6, 6, 8]
  id element: [0,0..]

  maxlength:
  id: []

  minlength:
  NOT A MONOID
-}


-- q2 (this was not covered in class - these are my notes nonetheless.
-- unfortunately there is no recording of me going through this work.
-- I hope my notes make sense to you!)
{- 2:
  Proofs about monoids.
  Set: lists
  Op: ++
  Id: []

  Associativity:
  for all x,y,z,
  x ++ (y ++ z) = (x ++ y) ++ z

  by induction on x:
  base case:
  [] ++ (y ++ z) = y ++ z
                 = ([] ++ y) ++ z

  inductive case:
  IH: x ++ (y ++ z) = (x ++ y) ++ z
  goal: (a:x) ++ (y ++ z) = ((a:x) ++ y) ++ z

  (a:x) ++ (y ++ z) = a:(x ++ (y ++ z)) -- definition of ++
                    = a:((x ++ y) ++ z) -- rewriting inductive hyp
                    = a:(x ++ y) ++ z   -- definition of ++
                    = ((a:x) ++ y) ++ z -- definition of ++
                    QED

  proof of (x ++ [] = x):
  by induction on x
  base case:
    ([] ++ [] = []) QED immediately
  inductive case:
    IH: x ++ [] = x
    goal: (a:x) ++ [] = a:x

    (a:x) ++ [] = a:(x ++ []) -- definition of ++
                = a:(x)       -- inductive hyp
                = a:x
                QED

  proof of ([] ++ x = x)
  no induction needed. provided directly from definition of ++
  [] ++ x = x 
          QED

 -}

-- parse, don't validate
-- word frequencies exercise

breakIntoWords :: String -> [String]
breakIntoWords = words

removePunctuation :: String -> String
removePunctuation s = filter (\x -> not (isPunctuation x)) s

sortStrings :: [String] -> [String]
sortStrings = sort

-- this is a this thing
-- [[this, this], [is]]

groupSame :: [String] -> [NonEmpty String]
groupSame = Data.List.NonEmpty.group

sortByLength :: [NonEmpty String] -> [String]
sortByLength ss = map Data.List.NonEmpty.head (reverse (sortOn length ss))

takeLongest :: Int -> [String] -> [String]
takeLongest = take

getReport :: String -> Int -> [String]
getReport s n = takeLongest n
              $ sortByLength
              $ groupSame
              $ sortStrings
              $ map removePunctuation
              $ breakIntoWords s

2023-08-13 Sun 12:52

Announcements RSS